package com.example.demo.controller;

import com.example.demo.pojo.*;
import com.example.demo.service.MailService;
import com.example.demo.service.RateService;
import com.example.demo.service.UserService;
import com.example.demo.service.UtilityBillService;
import com.example.demo.utils.AliOssUtil;
import com.example.demo.utils.BillPdfUtil;
import com.example.demo.utils.ThreadLocalUtil;
import jakarta.validation.constraints.Null;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import com.example.demo.controller.RateController;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

@RestController
@RequestMapping("/utilitybill")
@EnableScheduling
public class UtilityBillController {

    @Autowired
    private UtilityBillService utilityBillService;
    @Autowired
    private UserService userService;
    @Autowired
    private MailService mailService;
    @Autowired
    private RateService rateService;


    public boolean Authentication() {
        Map<String, Object> map = ThreadLocalUtil.get();
        String phonenumber = (String) map.get("phonenumber");
        User u = userService.findByphoneNumber(phonenumber);
        if (u.getUsertype() != 1) {
            return false;
        }
        return true;
    }

    public boolean UserStatus(String phonenumber){
        User u=userService.findByphoneNumber(phonenumber);
        if (u.getUserstatus()==0){
            return true;
        }
        return false;
    }

    public double getElectricityCost(double electricityusage) {
        List<ElectricityRate> rates = rateService.getelectricity();
        double totalCost = 0.0;
        double usage = electricityusage;
        for (ElectricityRate rate : rates) {
            if (usage > 0) {
                double startValue = rate.getStartvalue();
                double endValue = rate.getEndvalue();
                double costPerUnit = rate.getCostperunit();

                // 计算当前阶梯的实际使用电量
                double usedInThisTier = Math.min(usage, endValue - startValue);

                // 计算当前阶梯的费用
                totalCost += usedInThisTier * costPerUnit;

                // 减去已计算的电量
                usage -= usedInThisTier;
            }
        }

        return totalCost;
    }

    public double getWaterCost(double waterusage) {
        List<WaterRate> rates = rateService.getwater();
        double totalCost = 0.0;
        double usage = waterusage;
        for (WaterRate rate : rates) {
            if (usage > 0) {
                double startValue = rate.getStartvalue();
                double endValue = rate.getEndvalue();
                double costPerUnit = rate.getCostperunit();

                // 计算当前阶梯的实际使用水量
                double usedInThisTier = Math.min(usage, endValue - startValue);

                // 计算当前阶梯的费用
                totalCost += usedInThisTier * costPerUnit;

                // 减去已计算的水量
                usage -= usedInThisTier;
            }
        }
        return totalCost;
    }


    @GetMapping("/downloadBill")
    public Result<String> downloadBill(@RequestParam Integer billid) throws Exception {
        UtilityBill bill = utilityBillService.getBybillid(billid); // 获取账单信息
        BillPdfUtil generator = new BillPdfUtil();
        ByteArrayOutputStream byteArrayOutputStream = generator.generatePdf(bill);

        // 使用UUID生成文件名
        String filename = "bill_" + billid + ".pdf";
        String fileUuid = UUID.randomUUID().toString() + ".pdf";

        // 上传PDF文件到OSS
        String url = AliOssUtil.uploadFile(fileUuid, new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));

        // 返回文件下载URL
        return Result.success(url);
    }



    /**
     * 通过@RequestMapping注解，将该方法与"/utilitybillinfo"的URL路径绑定，用于处理查询用户水电费信息的请求。
     * 方法返回一个包含水电费信息列表的结果对象。
     *
     * @return Result<List<UtilityBill>> 返回一个结果对象，其中包含用户的所有水电费信息列表。
     */
    @GetMapping("/utilitybillinfo")
    public Result<PageBean<UtilityBill>> utilitybillinfo(@RequestParam(required = false) int pageNum,
                                                         @RequestParam(required = false) int pageSize) {
        // 从线程本地存储中获取用户信息映射，这通常是在用户会话上下文中存储的信息。
        Map<String,Object> map= ThreadLocalUtil.get();
        // 提取用户ID，用于后续查询用户的水电费信息。
        int userid = (int) map.get("userid");
        // 根据用户ID查询该用户的水电费信息列表。
        PageBean<UtilityBill> utilitybill = utilityBillService.findByuserid(userid, pageNum, pageSize);
        // 将查询到的水电费信息列表封装在一个成功的结果对象中返回。
        return Result.success(utilitybill);
    }

    @GetMapping("/getmonth")
    public Result<UtilityBill> sendUtilityBillMail() {
        Map<String,Object> map= ThreadLocalUtil.get();
        // 提取用户ID，用于后续查询用户的水电费信息。
        int userid = (int) map.get("userid");
        UtilityBill ub= utilityBillService.selectendnull(userid);
        return Result.success(ub);

    }

    @GetMapping("/r-utilitybillinfo")
    public Result<PageBean<UtilityBill>> r_utilitybillinfo(@RequestParam(required = false) int pageNum,
                                                            @RequestParam(required = false) int pageSize,
                                                            @RequestParam(required = false) String realname) {
        if(!Authentication()){
            return Result.error("权限不足");
        }

        // 根据用户ID查询该用户的水电费信息列表。
        PageBean<UtilityBill> utilitybill = utilityBillService.findByrealname(realname, pageNum, pageSize);
        // 将查询到的水电费信息列表封装在一个成功的结果对象中返回。
        return Result.success(utilitybill);
    }


    private void newutilitybill(int userid,double remainingbalance) {
        // 创建新账单
        utilityBillService.newutilitybill(userid,remainingbalance);
    }

    @PostMapping("/newutilitybill")
    public Result newutilitybills() {
        List<User> userList = userService.findAllUsers();
        for(User u : userList) {
            if (u.getUserstatus()==1||u.getUsertype()==1)
                continue;
            newutilitybill(u.getUserid(), u.getAccountbalance());
            sendUtilityBillMail(u.getEmail());
        }
        return Result.success();
   }

   public void sendUtilityBillMail(String email) {
       mailService.sendMail(email, "您的新月度账单已生成！", "您的新月度账单已生成！请前往水电费预交费管理系统进行查看与缴费！");
   }

    @Scheduled(cron = "0 */4 * * * ?")
    public void updatebill(){
        List<User> userList = userService.findAllUsers();
        for (User u : userList) {
            UtilityBill ub= utilityBillService.selectendnull(u.getUserid());
            if(ub!=  null) {
                double watercost = getWaterCost(ub.getWaterusage() + 0.01);
                double electricitycost = getElectricityCost(ub.getElectricityusage() + 0.01);
                double totalamount = watercost + electricitycost;
                Random random = new Random();

                // 生成0.01到0.05之间的随机数
                BigDecimal min = new BigDecimal("0.01");
                BigDecimal max = new BigDecimal("0.05");
                BigDecimal range = max.subtract(min);
                BigDecimal randomNumber = min.add(range.multiply(BigDecimal.valueOf(random.nextDouble())));

                // 设置精度为两位小数
                randomNumber = randomNumber.setScale(2, RoundingMode.HALF_UP);
                double addwaterusage =randomNumber.doubleValue();;
                utilityBillService.update(ub.getWaterusage() +addwaterusage,watercost, ub.getElectricityusage() + 0.01,electricitycost,totalamount, u.getAccountbalance() -totalamount, ub.getBillid());
                int userid = u.getUserid();
                userService.updateaccountbalance(userid,u.getAccountbalance() -totalamount);
            }
        }
    }



    @Scheduled(cron = "1 0 0 1 * ?")
    public void createNewUtilityBillAutomatically() {
        List<User> userList = userService.findAllUsers();
        for (User u : userList) {
            if (u.getUserstatus()==1||u.getUsertype()==1)
                continue;
            newutilitybill(u.getUserid(), u.getAccountbalance());
        }
    }


    /**
     * 定时任务：在每天晚上11点59分55秒执行，用于设置所有用户的电费账单的结束时间。
     * 通过查询所有用户，然后检查每个用户的电费账单是否需要设置结束时间。
     * 如果电费账单存在且尚未设置结束时间，则设置结束时间，并更新用户的账户余额，同时发送电费账单至用户邮箱。
     */
    @Scheduled(cron = "55 59 23 L * ?")
    public void setUtilityBillendtime() {
        // 查询所有用户
        List<User> userList = userService.findAllUsers();
        // 遍历所有用户
        for (User u : userList) {
            // 根据用户ID查询电费账单，判断是否存在未设置结束时间的账单
            UtilityBill ub = utilityBillService.selectendnull(u.getUserid());
            if (ub != null) {
                // 如果电费账单存在，获取账单的剩余余额
                // 为该电费账单设置结束时间
                Double accountbalance = ub.getRemainingbalance();
                // 获取用户ID
                int userid = u.getUserid();
                // 更新用户的账户余额
                userService.updateaccountbalance(userid,accountbalance);
                // 设置电费账单的结束时间
                utilityBillService.setendtime(ub.getBillid());
                // 发送电费账单至用户邮箱
                sendUtilityBillMail(u.getEmail());
            }
        }
    }



//    每隔1分钟执行一次：0 */1 * * * ?
//    每月1号凌晨1点执行一次：0 0 1 1 * ?
//    每月最后一天23点执行一次：0 0 23 L * ?

}
